#ifndef SKIAGRAPHICSTATE_H
#define SKIAGRAPHICSTATE_H

#include "_DoObject.h"
#include "SkBitmap.h"
#include "SkPaint.h"
#include "SkCanvas.h"
#include "SkRect.h"
#include "SkImageEncoder.h"
#include "SkPath.h"
#include "SkMatrix.h"
#include "SkFontHost.h"
#include "SkColor.h"
#include "SkTypeface.h"
#include <stack>

class SkiaGraphicState : public _DoObject
{
public:	
	class GraphicState
	{
	protected:
		void clonePath(SkPath &dst, const SkPath &src) {
			uint32_t cb = src.writeToMemory(0);
			unsigned char *pathblob = new unsigned char[cb];
			cb = src.writeToMemory(pathblob);
			
			dst.readFromMemory(pathblob);
			delete []pathblob;
		}
		
		void clone(const GraphicState &in) {
			clonePath(mCurrPath, in.mCurrPath);
			mCurrPoint = in.mCurrPoint;
			mFontDict = in.mFontDict;
			mFontSize = in.mFontSize;
			mColor = in.mColor;
			mLineWidth = in.mLineWidth; mMiterLimit = in.mMiterLimit; mLineJoin = in.mLineJoin; mLineCap = in.mLineCap;
			mCtm = in.mCtm;
			mColorSpace = in.mColorSpace;
		}
	public:
		enum ColorSpace {
			eRGB,
			eGray,
			eCMYK,
		};
	public:
		SkPath 	mCurrPath;
		
		SkPoint mCurrPoint;
		
		CRefPtr< _DoObject > mFontDict;

		float mFontSize;
		
		SkColor mColor;
		
		SkScalar mLineWidth, mMiterLimit;
		
		int mLineJoin, mLineCap;
		
		SkMatrix mCtm;
		
		ColorSpace mColorSpace;
		
		GraphicState() 
			: mCurrPath()
			, mCurrPoint()
			, mFontDict()
			, mFontSize(1)
			, mColor()
			, mLineWidth(0.f)
			, mMiterLimit(0.f)
			, mLineJoin(0)
			, mLineCap(0)
			, mCtm()
			, mColorSpace(eRGB) {			
		}
		
		~GraphicState() {
		}
		
		GraphicState(const GraphicState& copy)
		{
			clone(copy);
		}

		GraphicState& operator=(const GraphicState& copy)
		{
			if (this != &copy) {
				clone(copy);
			}
			return *this;
		}
		
		void text(SkPaint &paint, float scale);
		
		void stroke(SkPaint &paint);
		
		void fill(SkPaint &paint);
	};
	
protected:
	SkiaGraphicState(const SkiaGraphicState&);
	SkiaGraphicState& operator=(const SkiaGraphicState&);
	
	SkBitmap &mBitmap;
	
    SkCanvas mCanvas;
	
	float mScale;
		
	SkPaint mPaint;
	
	SkTypeface *mFont;
	
	GraphicState mState;
	
	std::stack< GraphicState > mStateStack;
	
	void convertString(DoString* str, std::string& oss);
	
	void RGBtoCMYK(float color[4]);
	
	void CMYKtoRGB(float color[4]);
public:
	SkiaGraphicState(SkBitmap &bitmap, float scale);
	virtual ~SkiaGraphicState();

	const SkMatrix& getCtm() { return mState.mCtm; }
	
	virtual void gsave();
	
	virtual void grestore();
	
	virtual void rectclip(int left, int top, int right, int bottom);
	
	virtual void setgray(float gray);
	
	virtual void selectfont(CRefPtr< _DoObject > font, float fontMatrix[6]);
	
	virtual void moveto(float x, float y);
	
	virtual void show(CRefPtr< _DoObject > str);
	
	virtual SkPoint dtransform(float mat[6], SkPoint pt);
	
	virtual void rmoveto(float x, float y);
	
	virtual SkPoint currentpoint();
	
	virtual void concatmatrix(float m1[6], float m2[6], float out[6]);
	
	virtual void setlinewidth(float x);

	virtual void setlinecap(int x);

	virtual void setlinejoin(int x);

	virtual void setdash(float dash[], float dash_phase);

	virtual void setmiterlimit(float x);
	
	virtual void lineto(float x, float y);
	
	virtual void stroke();
	
	virtual void rlineto(float x, float y);
	
	virtual void closepath();
	
	virtual void clip();
	
	virtual void newpath();
	
	virtual void concat(const SkMatrix&);
	
	virtual void setcolorspace(const char *name);
	
	virtual void image(int w, int h, float mat[6], const std::ostringstream& oss);
	
	virtual void showpage();
	
	virtual void eoclip();
	
	virtual void fill();
	
	virtual void curveto(float x1, float y1, float x2, float y2, float x3, float y3);
	
	virtual void setrgbcolor(float red, float green, float blue);
	
	virtual void scale(float sx, float sy);
	
	virtual GraphicState::ColorSpace currentcolorspace() { return mState.mColorSpace;}
	
	virtual SkPoint transform(float mat[6], SkPoint pt);
	
	virtual SkPoint stringwidth(CRefPtr< _DoObject > str);
	
	virtual SkPoint idtransform(float mat[6], SkPoint pt);
	
	virtual void awidthshow(float cx, float cy, int achar, float ax, float ay, CRefPtr< _DoObject > str);
	
	virtual void setfont(CRefPtr< _DoObject > font);
	
	virtual void setcmykcolor(float c, float m, float y, float k);
};

#endif // SKIAGRAPHICSTATE_H
